package org.finesys.common.netty.websocket.stomp.support;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.codec.stomp.StompSubframeAggregator;
import io.netty.handler.codec.stomp.StompSubframeDecoder;
import io.netty.handler.codec.stomp.StompSubframeEncoder;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.finesys.common.netty.websocket.handler.HttpServerHandler;
import org.finesys.common.netty.websocket.stomp.constants.StompVersion;
import org.finesys.common.netty.websocket.stomp.handler.StompServerHandler;
import org.finesys.common.netty.websocket.support.WebSocketEndpointConfig;

import java.util.List;

/**
 * stomp协议的解码器
 */
public class StompWebSocketProtocolDecoder extends MessageToMessageDecoder<WebSocketFrame> {
    // 初始化内部日志记录器
    private static final InternalLogger INTERNAL_LOGGER = InternalLoggerFactory.getInstance(HttpServerHandler.class);

    // WebSocket事件服务器
    private final StompWebSocketEndpointEventServer webSocketEndpointEventServer;

    // WebSocket端点配置
    private final WebSocketEndpointConfig webSocketEndpointConfig;

    // 事件执行器组
    private final EventExecutorGroup eventExecutorGroup;

    // 是否启用CORS
    private final boolean isCors;
    //stomp协议解码器
    private final StompWebSocketFrameEncoder stompWebSocketFrameEncoder = new StompWebSocketFrameEncoder();

    /**
     * StompWebSocketProtocolDecoder 构造函数
     *
     * @param webSocketEndpointEventServer WebSocket端点事件服务器，用于处理WebSocket事件
     * @param webSocketEndpointConfig      WebSocket端点配置，包含端点的各种配置信息
     * @param eventExecutorGroup           事件执行器组，用于处理异步事件
     * @param isCors                       是否启用跨域资源共享（CORS）
     */
    public StompWebSocketProtocolDecoder(StompWebSocketEndpointEventServer webSocketEndpointEventServer, WebSocketEndpointConfig webSocketEndpointConfig, EventExecutorGroup eventExecutorGroup, boolean isCors) {
        this.webSocketEndpointEventServer = webSocketEndpointEventServer;
        this.webSocketEndpointConfig = webSocketEndpointConfig;
        this.eventExecutorGroup = eventExecutorGroup;
        this.isCors = isCors;
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("stomp协议解码器事件触发");
        //握手完成事件处理
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            //获取stomp协议版本
            StompVersion stompVersion = StompVersion.findBySubProtocol(((WebSocketServerProtocolHandler.HandshakeComplete) evt).selectedSubprotocol());
            //设置stomp协议版本
            ctx.channel().attr(StompVersion.CHANNEL_ATTRIBUTE_KEY).setIfAbsent(stompVersion);
            // 添加WebSocketFrameAggregator以聚合WebSocket帧
            ctx.pipeline().addLast(new WebSocketFrameAggregator(Integer.MAX_VALUE));
            //stomp协议解码器
            ctx.pipeline().addLast(new StompSubframeDecoder());
            //stomp协议编码器
            ctx.pipeline().addLast(new StompSubframeEncoder());
            //stomp aggrelator
            ctx.pipeline().addLast(new StompSubframeAggregator(Integer.MAX_VALUE));
            //自定义stompx协议处理器
            ctx.pipeline().addLast(new StompServerHandler(webSocketEndpointEventServer, webSocketEndpointConfig, eventExecutorGroup));
            //删除stomp协议解码器
//            ctx.pipeline().remove(StompWebSocketClientPageHandler.INSTANCE);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        INTERNAL_LOGGER.error("stomp协议解码器异常", cause);
        super.exceptionCaught(ctx, cause);
    }


    @Override
    protected void decode(ChannelHandlerContext ctx, WebSocketFrame webSocketFrame, List<Object> out) {
        if (webSocketFrame instanceof TextWebSocketFrame || webSocketFrame instanceof BinaryWebSocketFrame) {
            out.add(webSocketFrame.content().retain());
        } else {
            ctx.close();
        }
    }

}
